This is the supplementary notes and examples for lecture 16.
It is based on data and examples seen in class
Built on the excellent tutorial from RStudio
If not already installed, the install leaflet:
install.packages("leaflet")
Then attach the library:
library(leaflet)
Bring in the other needed libraries:
library(sf)
library(tidyverse)
library(USAboundaries)
Creating a Leaflet map requires a few basic steps (not unsimular to ggplot):
Initialize a map widget by calling leaflet().
Add layers (i.e., features) to the map by using layer functions (e.g. addTiles, addMarkers, addPolygons,…)
Print the map widget to display it.
Here’s a basic example:
leaflet() %>%
addTiles() %>%
addMarkers(lng=-119.8489, lat=34.4140, popup="UCSB")
By default, leaflet sets the view of the map to the range of latitude/longitude data in the map layers
You can adjust these if needed using:
setView(): sets the center of the map view and the zoom level;
fitBounds(): fits the view into the rectangle [lng1, lat1] – [lng2, lat2];
clearBounds() clears the bound
The easiest way to add tiles is by calling addTiles() with no arguments; by default, OpenStreetMap tiles are used.
(leaflet() %>%
setView(lng=-119.8489, lat=34.4140, zoom = 12) %>%
addTiles())
Many third-party basemaps can be added using the addProviderTiles() function
As a convenience, leaflet provides a named list of all the third-party tile providers supported by the plugin: just type providers$ and choose from one of the options.
length(providers)
#> [1] 164
names(providers) %>%
head()
#> [1] "OpenStreetMap" "OpenStreetMap.Mapnik" "OpenStreetMap.DE"
#> [4] "OpenStreetMap.CH" "OpenStreetMap.France" "OpenStreetMap.HOT"
Note that some tile set providers require you to register. You can pass access tokens/keys, and other options, to the tile provider by populating the options argument with the providerTileOptions() function.
Below are a few examples:
leaflet() %>%
setView(lng=-119.8489, lat=34.4140, zoom = 12) %>%
addProviderTiles(providers$CartoDB)
leaflet() %>%
setView(lng=-119.8489, lat=34.4140, zoom = 12) %>%
addProviderTiles(providers$Stamen.Toner)
leaflet() %>%
setView(lng=-119.8489, lat=34.4140, zoom = 12) %>%
addProviderTiles(providers$Esri.WorldImagery)
leaflet() %>%
setView(lng=-119.8489, lat=34.4140, zoom = 12) %>%
addProviderTiles(providers$Stamen.TopOSMRelief)
You can stack multiple tile layers if the front tiles have some level of opacity. Here we layer the Stamen.TonerLines with aerial imagery
leaflet() %>%
setView(lng=-119.8489, lat=34.4140, zoom = 12) %>%
addProviderTiles(providers$Esri.WorldImagery) %>%
addProviderTiles(providers$Stamen.TonerLines, options = providerTileOptions(opacity = .5))
Markers are one way to identify point information on a map:
(starbucks = read_csv('../data/directory.csv') %>%
filter(City %in% c("Goleta", "Santa Barbara")) %>%
st_as_sf(coords = c("Longitude", "Latitude"), crs = 4326) %>%
select(store_name = `Store Name`, phone = `Phone Number`, address = `Street Address`, city = City, brand = Brand))
#> Simple feature collection with 11 features and 5 fields
#> geometry type: POINT
#> dimension: XY
#> bbox: xmin: -119.87 ymin: 34.4 xmax: -119.65 ymax: 34.44
#> geographic CRS: WGS 84
#> # A tibble: 11 x 6
#> store_name phone address city brand geometry
#> <chr> <chr> <chr> <chr> <chr> <POINT [°]>
#> 1 Hollister & St… 805-96… 7030 Marketpla… Goleta Starb… (-119.87 34.43)
#> 2 Goleta 805-68… 173 N. Fairvie… Goleta Starb… (-119.83 34.44)
#> 3 Montecito (805) … 1046 - A Coast… Santa … Starb… (-119.65 34.42)
#> 4 State & Cota, … 805-88… 539 State Stre… Santa … Starb… (-119.7 34.42)
#> 5 Ralph's - Sant… 805-56… 100 W Carrillo… Santa … Starb… (-119.7 34.42)
#> 6 800 State Stre… (805) … 800 State Stre… Santa … Starb… (-119.7 34.42)
#> 7 W Carrillo & D… 805-89… 208 West Carri… Santa … Starb… (-119.7 34.42)
#> 8 La Cumbre Plaza 805-56… 3815 State Str… Santa … Starb… (-119.75 34.44)
#> 9 Five Points Ce… (805) … 3957 State Str… Santa … Starb… (-119.75 34.44)
#> 10 State & Victor… 805-88… 1235 State Str… Santa … Starb… (-119.71 34.42)
#> 11 1990 Cliff Dri… 805-88… 1990 Cliff Dri… Santa … Starb… (-119.72 34.4)
Markers are added using the addMarkers or addAwesomeMarkers
Their default appearance is a blue dropped pin.
As with most layer functions, - the popup argument adds a message to be displayed on click - the label argument display a text label either on hover
leaflet() %>%
addProviderTiles(providers$CartoDB) %>%
addMarkers(data = starbucks, popup = ~store_name, label = ~city)
Using the Font Awesome Icons seen in lab one, we can make markers with more specific coloring and icons
We then use addAwesomeMarkers to spcifiy the icon we created using the icon argument:
icons = awesomeIcons(icon = 'coffee', markerColor = "green", library = 'fa', spin = TRUE)
leaflet(data = starbucks) %>% addProviderTiles(providers$CartoDB) %>%
addAwesomeMarkers(icon = icons, popup = ~store_name)
You can use HTML, CSS, and Java Script to modify your pop-ups
For example, we can associate the name of the Starbucks locations with their google maps URL as an hyper reference (href):
starbucks = starbucks %>%
mutate(url = paste0('https://www.google.com/maps/place/',
gsub(" ", "+", address), "+",
gsub(" ", "+", city)))
pop = paste0('<a href=', starbucks$url, '>', starbucks$store_name, "</a>")
head(pop)
#> [1] "<a href=https://www.google.com/maps/place/7030+Marketplace+Drive+Goleta>Hollister & Storke-Goleta</a>"
#> [2] "<a href=https://www.google.com/maps/place/173+N.+Fairview+Avenue+Goleta>Goleta</a>"
#> [3] "<a href=https://www.google.com/maps/place/1046+-+A+Coast+Village+Road,+Paseo+Nuevo+Shops+Santa+Barbara>Montecito</a>"
#> [4] "<a href=https://www.google.com/maps/place/539+State+Street+Santa+Barbara>State & Cota, Santa Barbara</a>"
#> [5] "<a href=https://www.google.com/maps/place/100+W+Carrillo+St+Santa+Barbara>Ralph's - Santa Barbara #680</a>"
#> [6] "<a href=https://www.google.com/maps/place/800+State+Street+Santa+Barbara>800 State Street</a>"
We can then add our custom popup to our icons:
leaflet(data = starbucks) %>%
addProviderTiles(providers$CartoDB) %>%
addAwesomeMarkers(icon = icons,
label = ~address, popup = pop)
Circle markers are much like regular circles (shapes), except their radius in onscreen pixels stays constant regardless of zoom level (z).
leaflet(data = starbucks) %>%
addProviderTiles(providers$CartoDB) %>%
addCircleMarkers(label = ~address, popup = pop)
Sometimes while mapping many points, it is useful to cluster them. For example lets plot all starbucks in the world!
all_sb = read_csv('../data/directory.csv') %>%
filter(!is.na(Latitude)) %>%
st_as_sf(coords = c("Longitude", "Latitude"), crs = 4326)
leaflet(data = all_sb) %>%
addProviderTiles(providers$CartoDB) %>%
addMarkers(clusterOptions = markerClusterOptions())
The palette argument can be any of the following:
The domain is the values - named by variable - that the color palette should range over
# ?colorFactor
# Create a palette that maps factor levels to colors
pal <- colorFactor(c("darkgreen", "navy"), domain = c("Goleta", "Santa Barbara"))
leaflet(data = starbucks) %>% addProviderTiles(providers$CartoDB) %>%
addCircleMarkers(color = ~pal(city), fillOpacity = .5, stroke = FALSE)
(covid = readr::read_csv('https://raw.githubusercontent.com/nytimes/covid-19-data/master/live/us-states.csv') %>%
filter(date == max(date)) %>%
right_join(USAboundaries::us_states(), by = c("state" = "name")) %>%
filter(!stusps %in% c("AK","PR", "HI")) %>%
st_as_sf())
#> Simple feature collection with 49 features and 20 fields
#> geometry type: MULTIPOLYGON
#> dimension: XY
#> bbox: xmin: -124.7258 ymin: 24.49813 xmax: -66.9499 ymax: 49.38436
#> geographic CRS: WGS 84
#> # A tibble: 49 x 21
#> date state fips cases deaths confirmed_cases confirmed_deaths
#> <date> <chr> <chr> <dbl> <dbl> <dbl> <dbl>
#> 1 2021-03-12 Alabama 01 5.02e5 10274 393700 8069
#> 2 2021-03-12 Arizona 04 8.30e5 16464 NA NA
#> 3 2021-03-12 Arkansas 05 3.26e5 5410 256519 4342
#> 4 2021-03-12 California 06 3.61e6 55132 3593106 55041
#> 5 2021-03-12 Colorado 08 4.43e5 6108 NA NA
#> 6 2021-03-12 Connecticut 09 2.89e5 7761 NA NA
#> 7 2021-03-12 Delaware 10 8.97e4 1494 NA NA
#> 8 2021-03-12 District of … 11 4.21e4 1038 42128 1038
#> 9 2021-03-12 Florida 12 1.96e6 32039 0 32039
#> 10 2021-03-12 Georgia 13 1.00e6 17570 807746 15370
#> # … with 39 more rows, and 14 more variables: probable_cases <dbl>,
#> # probable_deaths <dbl>, statefp <chr>, statens <chr>, affgeoid <chr>,
#> # geoid <chr>, stusps <chr>, lsad <chr>, aland <dbl>, awater <dbl>,
#> # state_name <chr>, state_abbr <chr>, jurisdiction_type <chr>,
#> # geometry <MULTIPOLYGON [°]>
Adding those cases counts to polygons over a YlOrRd color ramp
leaflet() %>%
addProviderTiles(providers$CartoDB) %>%
addPolygons(data = covid,
fillColor = ~colorQuantile("YlOrRd", confirmed_cases)(confirmed_cases),
color = NA,
label = ~state_name)
leaflet() %>%
addProviderTiles(providers$CartoDB.DarkMatter) %>%
addCircles(data = st_centroid(covid),
fillColor = ~colorQuantile("YlOrRd", cases)(cases),
color = NA,
fillOpacity = .5,
radius = ~cases/3,
label = ~cases)
https://labs.waterdata.usgs.gov/api/nldi/linked-data/nwissite/USGS-11120000/navigate/UT
Trance the Upper Tributary (UT) of the USGS-11120000
# site ID
id = "11120000"
# base URL
base ="https://labs.waterdata.usgs.gov/api/nldi/linked-data/"
# Reading sf for URLs in line
leaflet() %>%
addProviderTiles(providers$CartoDB) %>%
addPolylines(data = read_sf(paste0(base,'nwissite/USGS-',id,'/navigate/UT'))) %>%
addPolygons(data = read_sf(paste0(base,'nwissite/USGS-',id,'/basin')),
fillColor = "transparent", color = "black")
WMS tiles can be added directly to a map. Here we use the NEXRAD rainfall information (refelctivity) from the Iowa Mesonet Program
(You may need to scroll out to find an)
conus = filter(us_states(), !stusps %in% c("AK", "PR", "HI"))
leaflet() %>%
addProviderTiles(providers$CartoDB) %>%
addPolygons(data = st_union(conus), fillColor = "transparent",
color = "black", weight = 1) %>%
addWMSTiles(
"http://mesonet.agron.iastate.edu/cgi-bin/wms/nexrad/n0r.cgi",
layers = "nexrad-n0r-900913",
options = WMSTileOptions(format = "image/png", transparent = TRUE)
)
Uses Leaflet’s built-in layers control you can choose one of several base layers, and any number of overlay layers to view.
By defining groups, you have the ability to toogle layers, and overlays on/off.
leaflet() %>%
addProviderTiles(providers$CartoDB, group = "Grayscale") %>%
addProviderTiles(providers$Esri.WorldTerrain, group = "Terrain") %>%
addPolylines(data = read_sf(paste0(base,'nwissite/USGS-',id,'/navigate/UT'))) %>%
addPolygons(data = read_sf(paste0(base,'nwissite/USGS-',id,'/basin')), fillColor = "transparent", color = "black", group = "basin") %>%
addWMSTiles("http://mesonet.agron.iastate.edu/cgi-bin/wms/nexrad/n0r.cgi", layers = "nexrad-n0r-900913",
options = WMSTileOptions(format = "image/png", transparent = TRUE)) %>%
addLayersControl(overlayGroups = c("basin"), baseGroups = c("Terrain", "Grayscale"))
You can wrap your mapping code in functions to allow reusability
watershed_map = function(gage_id){
leaflet() %>%
addProviderTiles(providers$CartoDB) %>%
addPolylines(data = read_sf(paste0(base,'nwissite/USGS-',gage_id,'/navigate/UT'))) %>%
addPolygons(data = read_sf(paste0(base,'nwissite/USGS-',gage_id,'/basin')),
fillColor = "transparent", color = "black", group = "basin") %>%
addWMSTiles("http://mesonet.agron.iastate.edu/cgi-bin/wms/nexrad/n0r.cgi", layers = "nexrad-n0r-900913",
options = WMSTileOptions(format = "image/png", transparent = TRUE))
}
watershed_map("07382000")
watershed_map("07382000") %>%
addMeasure() %>%
addGraticule() %>%
addMiniMap()
watershed_map("07382000") %>%
addMeasure() %>%
addGraticule() %>%
leafem::addHomeButton(group = "basin") %>%
leafem::addMouseCoordinates()
leaflet(data = starbucks) %>%
addProviderTiles(providers$CartoDB) %>%
addCircleMarkers(
color = ~pal(city),
fillOpacity = .5,
stroke = FALSE,
popup = leafpop::popupTable(starbucks)
)
Making that table nicer…
leaflet(data = starbucks) %>% addProviderTiles(providers$CartoDB) %>%
addCircleMarkers(
color = ~pal(city), fillOpacity = .5,
stroke = FALSE,
popup = leafpop::popupTable(st_drop_geometry(starbucks[,1:5]), feature.id = FALSE, row.numbers = FALSE)
)
leafem and leafpop functionalitieslibrary(mapview)
mapview(starbucks)